﻿using System.Linq;
using System.Xml.Linq;

namespace Sidvall.Xml
{
	public static class XContainerExtension
	{
		#region Public Members

		#region GetElement

		public static XElement GetElement(this XContainer item, string elementName)
		{
			if (item == null)
				return null;
			if (string.IsNullOrWhiteSpace(elementName))
				return item as XElement;
			return item.Element(elementName);
		}

		public static XElement GetElement(this XContainer item, string[] elementNames)
		{
			if (item == null)
				return null;
			if (elementNames == null)
				return item as XElement;
			foreach (var elementName in elementNames)
			{
				item = item.Element(elementName);
				if (item == null)
					return null;
			}
			return item as XElement;
		}

		#endregion
		#region GetElements

		public static System.Collections.Generic.IEnumerable<XElement> GetElements(this XContainer item)
		{
			if (item == null)
				return null;
			return item.Elements();
		}

		public static System.Collections.Generic.IEnumerable<XElement> GetElements(this XContainer item, string elementName)
		{
			if (item == null)
				return null;
			if (string.IsNullOrWhiteSpace(elementName))
				return item.Elements();

			return item.Elements(elementName);
		}

		public static System.Collections.Generic.IEnumerable<XElement> GetElements(this XContainer item, string[] elementNames)
		{
			int iMax;

			if (item == null)
				return null;
			if (elementNames == null)
				return item.Elements();
			if (!elementNames.Any())
				return item.Elements();
			iMax = elementNames.Length - 1;
			for (int i = 0; i < iMax; i++)
			{
				item = item.Element(elementNames[i]);
				if (item == null)
					return null;
			}

			return item.Elements(elementNames[iMax]);
		}

		#endregion
		#region GetFirstDescendant

		public static XElement GetFirstDescendant(this XContainer item)
		{
			return GetFirstDescendant(item, null);
		}
		public static XElement GetFirstDescendant(this XContainer item, string elementName)
		{
			if (item == null)
				return null;
			if (string.IsNullOrWhiteSpace(elementName))
				return item.Descendants().FirstOrDefault();
			return item.Descendants(elementName).FirstOrDefault();
		}

		#endregion
		#region GetFirstDescendantInnerXml

		public static string GetFirstDescendantInnerXml(this XContainer item)
		{
			return GetFirstDescendantInnerXml(item, null);
		}
		public static string GetFirstDescendantInnerXml(this XContainer item, string elementName)
		{
			item = GetFirstDescendant(item, elementName);

			return ReadInnerXml(item);
		}

		#endregion
		#region GetInnerXml

		public static string GetInnerXml(this XNode item)
		{
			return ReadInnerXml(item);
		}

		public static string GetInnerXml(this XContainer item, string elementName)
		{
			item = GetElement(item, elementName);

			return ReadInnerXml(item);
		}

		public static string GetInnerXml(this XContainer item, string[] elementNames)
		{
			item = GetElement(item, elementNames);

			return ReadInnerXml(item);
		}

		#endregion

		#endregion
		#region Private Members

		#region ReadInnerXml

		private static string ReadInnerXml(XNode item)
		{
			if (item == null)
				return null;
			using (var reader = item.CreateReader())
			{
				reader.MoveToContent();
				return reader.ReadInnerXml();
			}
		}

		#endregion

		#endregion
	}
}
